package com.weaver.view;

import com.weaver.controller.Controller;
import com.weaver.model.Model;

import javax.swing.*;
import java.awt.*;
import java.util.Observable;
import java.util.Observer;

/**
 * View class - Graphical user interface for the Weaver game
 * Implements Observer interface to update the UI when model state changes
 */
public class View extends JFrame implements Observer {
    private Model model;
    private Controller controller;
    
    private BoardPanel boardPanel;
    private KeyboardPanel keyboardPanel;
    private ControlPanel controlPanel;
    
    private JLabel statusLabel;
    
    /**
     * Constructor
     * @param model game model
     * @param controller game controller
     */
    public View(Model model, Controller controller) {
        this.model = model;
        this.controller = controller;
        
        // Register as an observer of the model
        model.addObserver(this);
        
        // Set window properties
        setTitle("Weaver Game");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(650, 750);
        setLocationRelativeTo(null);
        
        // Create UI components
        initComponents();
        
        // Show window
        setVisible(true);
    }
    
    /**
     * Initialize UI components
     */
    private void initComponents() {
        // Create main panel
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout(10, 10));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        
        // Create title panel
        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(new FlowLayout(FlowLayout.CENTER));
        
        JLabel startWordLabel = new JLabel("Start:" + model.getStartWord());
        startWordLabel.setFont(new Font("Arial Black", Font.PLAIN, 18));
        
        JLabel arrowLabel = new JLabel(" => ");
        arrowLabel.setFont(new Font("Arial Black", Font.PLAIN, 18));
        
        JLabel targetWordLabel = new JLabel("Target:" + model.getTargetWord());
        targetWordLabel.setFont(new Font("Arial Black", Font.PLAIN, 18));
        
        titlePanel.add(startWordLabel);
        titlePanel.add(arrowLabel);
        titlePanel.add(targetWordLabel);
        
        // Create game board panel
        boardPanel = new BoardPanel(model);
        
        // Create keyboard panel
        keyboardPanel = new KeyboardPanel(controller);
        
        // Create control panel
        controlPanel = new ControlPanel(model, controller);
        
        // Create status label
        statusLabel = new JLabel("Enter your first word");
        statusLabel.setHorizontalAlignment(SwingConstants.CENTER);
        statusLabel.setFont(new Font("Arial Black", Font.BOLD, 14));
        statusLabel.setForeground(new Color(150, 50, 250));
        statusLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        // Add components to main panel
        mainPanel.add(titlePanel, BorderLayout.NORTH);
        mainPanel.add(boardPanel, BorderLayout.CENTER);
        mainPanel.add(controlPanel, BorderLayout.EAST);
        
        // Create a panel for keyboard and status label
        JPanel southPanel = new JPanel(new BorderLayout());
        southPanel.add(statusLabel, BorderLayout.NORTH);
        southPanel.add(keyboardPanel, BorderLayout.CENTER);
        mainPanel.add(southPanel, BorderLayout.SOUTH);
        
        // Set content pane
        setContentPane(mainPanel);
        
        // Add keyboard listener
        addKeyListener(controller.getKeyAdapter());
        setFocusable(true);
    }
    
    /**
     * Update the UI
     * Called when model state changes
     * @param o observed object
     * @param arg parameter
     */
    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof Model) {
            // Update title
            updateTitle();
            
            // Update game board
            boardPanel.updateBoard();
            
            // Update status label
            updateStatusLabel();
            
            // Update control panel
            controlPanel.updateControls();
            
            // Request focus but don't steal it from keyboard buttons
            if (!(arg instanceof String)) {
                requestFocus();
            }
        }
    }
    
    /**
     * Update the title
     */
    private void updateTitle() {
        // If using random words, update the start and target words in the title
        if (model.isUseRandomWords()) {
            Container contentPane = getContentPane();
            JPanel mainPanel = (JPanel) contentPane;
            JPanel titlePanel = (JPanel) mainPanel.getComponent(0);
            
            JLabel startWordLabel = (JLabel) titlePanel.getComponent(0);
            JLabel targetWordLabel = (JLabel) titlePanel.getComponent(2);
            
            startWordLabel.setText("Start: " + model.getStartWord());
            targetWordLabel.setText("Target: " + model.getTargetWord());
        }
    }
    
    /**
     * Update the status label
     */
    private void updateStatusLabel() {
        if (model.isGameWon()) {
            statusLabel.setText("Mission complete! " + model.getStartWord() + " evolved into " + model.getTargetWord());
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(this,
                        "Brilliant! " + model.getStartWord() + " ➔ " + model.getTargetWord() + " achieved",
                        "Word Mastered", JOptionPane.INFORMATION_MESSAGE);
            });
        } else if (model.getAttemptsCount() == 0) {
            statusLabel.setText("Begin your transformation journey");
        } else {
            statusLabel.setText("Next attempt...");
        }

        if (model.isShowPath()) {
            java.util.List<String> path = model.findPath();
            if (!path.isEmpty()) {
                StringBuilder pathStr = new StringBuilder("Evolution Trail: ");
                for (String word : path) {
                    pathStr.append(word).append(" ▷ ");
                }
                pathStr.setLength(pathStr.length() - 2); // 移除最后箭头后的空格
                statusLabel.setText(pathStr.toString());
            } else {
                statusLabel.setText("Pathway not discoverable");
            }
        }
    }


    /**
     * Show error message
     * @param message error message
     */
    public void showError(String message) {
        statusLabel.setText(message);
        statusLabel.setForeground(new Color(200, 0, 0));
        
        // Reset color after 2 seconds
        new javax.swing.Timer(2000, e -> {
            statusLabel.setForeground(new Color(150, 50, 250));
            ((javax.swing.Timer)e.getSource()).stop();
        }).start();
    }
    
    /**
     * Get the controller
     * @return game controller
     */
    public Controller getController() {
        return controller;
    }
}